using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Rotempco.Core.ORM.Objects.Stores;
using System.Threading;
using Rotempco.Core.Logic;

namespace Rotempco.Core.ORM.Managers
{
    public class EncryptionStoreManager
    {
        #region [ Singleton ]

        public static EncryptionStoreManager Instance
        {
            get
            {
                return SingletonStore.Instance.GetInstance<EncryptionStoreManager>(true);
            }
        }

        #endregion

        private void UseSymmetricKeyMethod(string symmetricEncryptionKey, Action action)
        {
            string currentSymmetricEncryptionKey = EncryptionKeyStore.Instance.SymmetricEncryptionKey;
            try
            {
                EncryptionKeyStore.Instance.SymmetricEncryptionKey = symmetricEncryptionKey;
                action();
            }
            finally
            {
                EncryptionKeyStore.Instance.SymmetricEncryptionKey = currentSymmetricEncryptionKey;
            }
        }

        public void UseSymmetricKey(string symmetricEncryptionKey, Action action)
        {
            if (DatabaseManager.Instance.IsThreadInTransaction())
                UseSymmetricKeyMethod(symmetricEncryptionKey, action);
            else
            {
                ThreadLogic.RunInNewBlockingThread(() =>
                {
                    UseSymmetricKeyMethod(symmetricEncryptionKey, action);
                });
            }
        }

        private void UsePublicEncryptionKeyMethod(string publicEncryptionKey, Action action)
        {
            string currentPublicEncryptionKey = EncryptionKeyStore.Instance.PublicEncryptionKey;
            try
            {
                EncryptionKeyStore.Instance.PublicEncryptionKey = publicEncryptionKey;
                action();
            }
            finally
            {
                EncryptionKeyStore.Instance.PublicEncryptionKey = currentPublicEncryptionKey;
            }
        }

        public void UsePublicEncryptionKey(string publicEncryptionKey, Action action)
        {
            if (DatabaseManager.Instance.IsThreadInTransaction())
                UsePublicEncryptionKeyMethod(publicEncryptionKey, action);
            else
            {
                ThreadLogic.RunInNewBlockingThread(() =>
                {
                    UsePublicEncryptionKeyMethod(publicEncryptionKey, action);
                });
            }
        }


        private void DisableEncryptionMethod(Action action)
        {
            if (!EncryptionKeyStore.Instance.DisableEncryption.ContainsKey(ThreadId))
                EncryptionKeyStore.Instance.DisableEncryption.Add(ThreadId, true);

            action();

            EncryptionKeyStore.Instance.DisableEncryption.Remove(ThreadId);
        }

        public void DisableEncryption(Action action)
        {
            if (DatabaseManager.Instance.IsThreadInTransaction())
                DisableEncryptionMethod(action);
            else
            {
                ThreadLogic.RunInNewBlockingThread(() =>
                {
                    DisableEncryptionMethod(action);
                });
            }
        }


        internal bool IsEncryptionDisabled()
        {
            return EncryptionKeyStore.Instance.DisableEncryption.ContainsKey(ThreadId) && EncryptionKeyStore.Instance.DisableEncryption[ThreadId] == true; ;
        }


        private int ThreadId
        {
            get
            {
                return Thread.CurrentThread.ManagedThreadId;
            }
        }
    }
}
